package mundo;

import java.util.Arrays;

import arrayChimbo.ArrayChimbo;

public class Quine_McCluskey {

	private static int cantDigitos=0;

	public static void main(String[] args) {
		String[] variables = {};
		int[] minterminos = {4,8,10,11,12,15,9,14};
		//int[] minterminos = {0,1,2,5,6,7,8,9,10,14};
		funcionSimplificada(variables, minterminos);
	}

	/**
	 * 
	 * @param variables
	 * @param minterminos
	 * @return
	 */
	public static String funcionSimplificada(String[] variables,int[]minterminos)
	{
		//0) TODO Revisar que los parametros que entran tienen la forma esperada
		
		//1) Ordenar los minterminos.
		Arrays.sort(minterminos);
		double mayor = minterminos[minterminos.length-1];

		//2) Encontar la cantidad de bits necesarios para su representacion.
		cantDigitos=(int) ((Math.log(mayor)/Math.log(2))+1);
		int filas = minterminos.length;

		//3) Crear un arreglo con la representacion binaria de los minterminos.
		ArrayChimbo<String> mTerminos= new ArrayChimbo<String>();
		for (int j = 0; j < filas; j++) {

			String mintermBinario=Integer.toBinaryString(minterminos[j]);

			//3.a) Rellenar los ceros a la izquierda que faltan en algunos de los minterminos.
			int cerosFaltantes=(cantDigitos-mintermBinario.length());
			for (int k = 0; k < cerosFaltantes; k++) {
				mintermBinario="0"+mintermBinario;
			}
			mTerminos.agregarSinRepetir(mintermBinario);
		}

		//4) Empezar la reduccion iterativa, la informacion para la tabla de implicacion se guarda en los 2 primeros arreglos.
		ArrayChimbo<String> saveMinSimplificados = new ArrayChimbo<String>();
		ArrayChimbo<String> saveNomSimplificados = new ArrayChimbo<String>();
		ArrayChimbo<String> nombresTerminos = new ArrayChimbo<String>();
		for (int i = 0; i < minterminos.length; i++) {
			nombresTerminos.add(minterminos[i]+"");
		}
		simplificacionIterativa(saveMinSimplificados,mTerminos,saveNomSimplificados,nombresTerminos );

		//5)TODO Teniendo los minterminos ya simplificados se crea la tabla de implicacion.
		for (int i = 0; i < saveMinSimplificados.size(); i++) {
			System.out.println(saveNomSimplificados.get(i)+"     "+saveMinSimplificados.get(i));
		}

		return null;
	}

	/**
	 * 
	 * @param minSimplificados_1 
	 * @param minterminos 
	 * @param chuleados
	 * @param minTerminos_2
	 * @return
	 */
	private static void simplificacionIterativa(ArrayChimbo<String> minSimplificados_1, ArrayChimbo<String> minTerminos_2, ArrayChimbo<String> nomSimplificados_1, ArrayChimbo<String> nomTerminos_2) {

		//1) Se inicializan las variables que va a ser necesitadas.
		int alto=minTerminos_2.size();
		char[] minitermino1=new char[cantDigitos];
		char[] minitermino2=new char[cantDigitos];
		ArrayChimbo<String> termminosSimplificados_3= new ArrayChimbo<String>();
		ArrayChimbo<String> nombresSimplificados_3= new ArrayChimbo<String>();

		boolean[] chuleados=new boolean[alto];
		for (int i = 0; i < chuleados.length; i++) 
		{chuleados[i]=false;}

		//2) Se comparan los minterminos entre ellos. Se van chuleando y guardando los que se pueden agrupar.
		for (int j = 0; j < alto; j++) {
			minitermino1=minTerminos_2.get(j).toCharArray();
			for (int j2 = j; j2 < alto; j2++) {
				minitermino2=minTerminos_2.get(j2).toCharArray();
				if(agrupables(minitermino1,minitermino2))
				{
					if(termminosSimplificados_3.agregarSinRepetir(cadenaConRaya(minitermino1,minitermino2)))
					{
						nombresSimplificados_3.add(nomTerminos_2.get(j)+","+nomTerminos_2.get(j2));
					}
					chuleados[j]=true;
					chuleados[j2]=true;
				}
			}
		}

		//3) Los que no fueron chuleados Se guardan pues ya estan maximamente simplificados.
		int contChulos=0;
		for (int i = 0; i < chuleados.length; i++) {
			if(chuleados[i]==false)
			{
				minSimplificados_1.agregarSinRepetir(minTerminos_2.get(i));
				nomSimplificados_1.agregarSinRepetir(nomTerminos_2.get(i));
			}
			else
				contChulos++;
		}

		for (int i = 0; i < termminosSimplificados_3.size(); i++) 
		{System.out.println(nombresSimplificados_3.get(i)+" : "+termminosSimplificados_3.get(i));}

		//4) Cuando no se haya chuleado ninguno, se acaba la recurcion.
		if(contChulos>0)
		{
			System.out.println("----------------------------------------\n");
			simplificacionIterativa(minSimplificados_1, termminosSimplificados_3,nomSimplificados_1,nombresSimplificados_3);
		}

	}

	/**
	 * 
	 * @param fila1
	 * @param fila2
	 * @return
	 */
	private static boolean agrupables(char[] fila1, char[] fila2) {
		int contador=0;
		for (int i = 0; i < fila1.length; i++) {
			if(fila1[i]!=fila2[i])
			{
				contador++;
			}
		}
		return (contador==1);
	}

	private static String cadenaConRaya(char[] fila1, char[] fila2) {
		String rta="";
		for (int i = 0; i < fila1.length; i++) {
			rta+=(fila1[i]==fila2[i])?fila1[i]:"-";
		}
		return rta;
	}

}